package com.uchiha.nova.core.tool.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import com.alibaba.fastjson2.JSONObject;
import com.uchiha.nova.core.tool.api.R;
import com.uchiha.nova.core.tool.constant.HeaderConstant;
import com.uchiha.nova.core.tool.support.AuthToken;
import com.uchiha.nova.core.tool.support.NovaUser;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

import org.springframework.data.redis.core.RedisTemplate;


import java.util.HashMap;
import java.util.Map;

/**
 * @author 周林静
 * @Date 2021/4/29 16:12
 * @Version 1.0
 */
@Slf4j
public class AuthUtil {

    public static NovaUser getUser() {
        HttpServletRequest request = WebUtil.getRequest();
        if (request == null) {
            return null;
        }

        NovaUser novaUser = new NovaUser();
        novaUser.setUserId(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_ID)) ? Long.valueOf(request.getHeader(HeaderConstant.NOVA_USER_ID)) : 1L);
        novaUser.setUserName(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USERNAME)) ? request.getHeader(HeaderConstant.NOVA_USERNAME) : "");
        novaUser.setTenantId(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_TENANT)) ? request.getHeader(HeaderConstant.NOVA_USER_TENANT) : "1");
        novaUser.setRoleName(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_ROLE)) ? request.getHeader(HeaderConstant.NOVA_USER_ROLE) : "1");
        novaUser.setPostId(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_POST)) ? request.getHeader(HeaderConstant.NOVA_USER_POST) : "1");
        novaUser.setDeptId(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_DEPT)) ? request.getHeader(HeaderConstant.NOVA_USER_DEPT) : "1");
        novaUser.setCompanyId(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_COMPANY)) ? request.getHeader(HeaderConstant.NOVA_USER_COMPANY) : "1");
        novaUser.setType(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_USER_ORGTYPE)) ? request.getHeader(HeaderConstant.NOVA_USER_ORGTYPE) : "1");
        novaUser.setDataAuth(ObjectUtil.isNotEmpty(request.getHeader(HeaderConstant.NOVA_DATA_AUTH)) ? request.getHeader(HeaderConstant.NOVA_DATA_AUTH) : "1");
        return novaUser;
    }

    public static AuthToken getToken(NovaUser user, String tokenKey, Long expireTime, Long refreshTime) {
        Long time = System.currentTimeMillis();
        AuthToken authToken = new AuthToken();
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(user));
        jsonObject.put("expired_time", String.valueOf(time + expireTime));

        log.info("getToken:{}", jsonObject);
        Map<String, Object> map = jsonObject;
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("token_type", "access_token");
        authToken.setAccessToken(JWTUtil.createToken(headerMap, map, tokenKey.getBytes()));
        map.put("expired_time", String.valueOf(time + refreshTime));
        headerMap.put("token_type", "refresh_token");
        map.put("refresh_time", String.valueOf(expireTime));
        authToken.setRefreshToken(JWTUtil.createToken(headerMap, map, tokenKey.getBytes()));
        return authToken;
    }

    public static boolean verifyToken(String token, String tokenKey) {
        return JWTUtil.verify(token, tokenKey.getBytes());
    }

    public static boolean isExpired(String token) {
        Long now = System.currentTimeMillis();
        final JWT jwt = JWTUtil.parseToken(token);
        JSONObject jsonObject = JSONObject.from(jwt.getPayload().getClaimsJson());
        log.info("isExpired:{}", jsonObject);
        return now.compareTo(jsonObject.getLong("expired_time")) >= 0;

    }

    public static NovaUser getUserByToken(String token) {
        final JWT jwt = JWTUtil.parseToken(token);
        log.info("getUserByToken:{}", jwt.getPayload().getClaimsJson());
        NovaUser novaUser = jwt.getPayload().getClaimsJson().toBean(NovaUser.class);
        return novaUser;
    }

    public static R refreshToken(String refreshToken, String tokenKey) {
        if (!verifyToken(refreshToken, tokenKey)) {
            return R.fail("无效的refreshToken");
        }
        final JWT jwt = JWTUtil.parseToken(refreshToken);

        log.info("refreshToken-header:{}", jwt.getHeader().getClaimsJson());
        JSONObject headerJson = JSONObject.from(jwt.getHeader().getClaimsJson());
        String token_type = headerJson.getString("token_type");
        if (!"refresh_token".equals(token_type)) {
            return R.fail("请使用refreshToken");
        }

        log.info("refreshToken-payload:{}", jwt.getPayload().getClaimsJson());
        JSONObject payloadJson = JSONObject.from(jwt.getPayload().getClaimsJson());
        String refresh_time = payloadJson.getString("refresh_time");

        Map<String, Object> map = payloadJson;
        Long time = System.currentTimeMillis();
        String value = String.valueOf(time + Long.valueOf(refresh_time));
        map.put("expired_time", value);
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("token_type", "access_token");
        String token1 = JWTUtil.createToken(headerMap, map, tokenKey.getBytes());
        return R.data(token1);
    }
}

